﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DDD {

    /// <summary>
    /// バウンディングスフィア
    /// </summary>
    /// <remarks>
    /// <dic>BoundingSphere</dic>はノードを囲う球でカリング、ピッキングなどに使われます。
    /// コリジョンの検出には使われません。
    ///  バウンディングスフィアは<see cref="Node"/>に<see cref="BoundingVolume"/>コンポーネントを追加し、
    /// <see cref="BoundingVolume.SetBoundingSphere"/>メソッドによって付加されます。
    /// この<see cref="BoundingVolume"/>に付加されたバウンディングスフィアをローカルのバウンディングスフィアと言います。
    /// １つシーンが<see cref="World.Freeze"/>されるとシーンの下から子ノードのバウンディングボックスを囲うように
    /// ノードのバウンディングスフィアが形成されていきます。このノードのバウンディングボリュームを
    /// グローバルのバウンディングスフィアと言います。
    /// またこのような階層構造をバウンディングボリューム階層といいます。
    /// ユーザーが<dic>BoundingSphere</dic>型をインスタンス化することはできず、
    /// エンジン側が作成したものを戻り値で受け取ります。
    /// アニメート可能、エクスポート可能。
    /// </remarks>
    public struct BoundingSphere : IAnimatable<float>, IExportable<float> {
        /// <summary>
        /// コンストラクター
        /// </summary>
        /// <param name="radius">半径</param>
        /// <param name="x">原点のX座標</param>
        /// <param name="y">原点のY座標</param>
        /// <param name="z">原点のZ座標</param>
        public BoundingSphere (float radius, float x, float y, float z)
            : this () {
            X = x;
            Y = y;
            Z = z;
            Radius = radius;
        }

        /// <summary>
        /// このバウンディングスフィアの有効無効フラグ
        /// </summary>
        /// <remarks>
        /// このバウンディングスフィアが有効なときtrueを返し、そうでない時はfalseを返します。
        /// </remarks>
        public bool IsValid {
            get { return true; }
        }

        /// <summary>
        /// バウンディングスフィアの半径
        /// </summary>
        /// <value>バウンディングスフィアの半径です。</value>
        public float Radius { get; private set; }

        /// <summary>
        /// バウンディングスフィアの中心のX座標
        /// </summary>
        /// <value>バウンディングスフィアの中心のX座標</value>
        public float X { get; private set; }

        /// <summary>
        /// バウンディングスフィアの中心のX座標
        /// </summary>
        /// <value>バウンディングスフィアの中心のX座標</value>
        public float Y { get; private set; }

        /// <summary>
        /// バウンディングスフィアの中心のX座標
        /// </summary>
        /// <value>バウンディングスフィアの中心のX座標</value>
        public float Z { get; private set; }


        /// <summary>
        /// コンポーネント数
        /// </summary>
        /// <value>コンポーネント数です。バウンディングボックスなので常に6が返ります。</value>
        public int ComponentCount { get { return 4; } }

        /// <summary>
        /// コンポーネント要素にアクセスするインデクサ
        /// </summary>
        /// <param pred="face">コンポーネント番号</param>
        /// <returns></returns>
        /// <exception cref="IndexOutOfRangeException"><dic>face &lt; 0 || face &gt; cc - 1</dic>の時<dic>IndexOutOfRange</dic></exception>
        public float this[int index] {
            get {
                if (index < 0 || index > ComponentCount - 1) {
                    throw new IndexOutOfRangeException ();
                }
                return 0;
            }
            set {
                if (index < 0 || index > ComponentCount - 1) {
                    throw new IndexOutOfRangeException ();
                }
            }
        }

        /// <summary>
        /// 現在のオブジェクトの状態を表す文字列を返します。
        /// </summary>
        /// <returns>現在のオブジェクトを説明する文字列。</returns>
        public override string ToString () {
            return string.Format("BoundingSphere, Radius={0}, X={1}, Y={2}, Z={3}", Radius, X, Y, Z);
        }

    }
}
